package com.efast.cafe.util;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.channels.FileChannel;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import com.efast.cafe.framework.bean.FileChunkInfo;
import com.efast.cafe.framework.exception.ServiceException;

public class FileUploadUtil extends FileUtil {

	/**
	 * 将文件流写入到指定文件中
	 * 
	 * @param destFile
	 * @param fis
	 * @throws IOException
	 *             void
	 * @Author Administrator
	 * @Date 2017年9月21日
	 */
	public static void saveFile(File destFile, InputStream fis) throws IOException {
		FileOutputStream fos = null;
		if (fis == null) {
			return;
		}
		try {
			fos = new FileOutputStream(destFile);
			byte[] b = new byte[1024];
			int len = fis.read(b);
			while (len != -1) {
				fos.write(b);
				len = fis.read(b);
			}
			fos.flush();

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} finally {
			if (fis != null) {
				fis.close();
			}
			if (fos != null) {
				fos.close();
			}
		}

	}

	/**
	 * 将文件追加到指定文件中
	 * 
	 * @param destFile
	 * @param srcFile
	 * @param append
	 * @throws IOException
	 *             void
	 * @Author Administrator
	 * @Date 2017年9月21日
	 */
	public static void saveFile(File destFile, File srcFile, boolean append) throws IOException {
		FileOutputStream fos = null;
		FileInputStream fis = null;
		if (srcFile == null) {
			return;
		}
		try {

			fos = new FileOutputStream(destFile, append);
			fis = new FileInputStream(srcFile);
			byte[] b = new byte[1024*4];
			int len = fis.read(b);
			while (len != -1) {
				fos.write(b,0,len);
				len = fis.read(b);
			}
			fos.flush();

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} finally {
			if (fis != null) {
				fis.close();
			}
			if (fos != null) {
				fos.close();
			}
		}
	}

	public static void saveFile(File destFile, InputStream ins, boolean append) throws IOException {
		FileOutputStream fos = null;
		if (ins == null) {
			return;
		}
		try {
			fos = new FileOutputStream(destFile, append);
			byte[] b = new byte[1024];
			int len = ins.read(b);
			while (len != -1) {
				fos.write(b);
				len = ins.read(b);
			}
			fos.flush();

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} finally {
			if (ins != null) {
				ins.close();
			}
			if (fos != null) {
				fos.close();
			}
		}
	}

	/**
	 * 将文件大小转换成合适的单位
	 * 
	 * @param length
	 * @return String
	 * @Author Administrator
	 * @Date 2017年9月14日
	 */
	public static String fileSizeUnitToString(long length) {
		String unit = null;
		int level = 0;
		double remainder = 0;
		do {
			remainder = length % 1024;
			length /= 1024;
			level++;
		} while (length >= 1024);
		switch (level) {
		case 0:
			unit = "B";
			break;
		case 1:
			unit = "KB";
			break;
		case 2:
			unit = "M";
			break;
		case 3:
			unit = "G";
			break;
		case 4:
			unit = "T";
			break;
		default:
			break;
		}
		DecimalFormat df = new DecimalFormat("#.000");
		remainder = 1.0 * remainder / 1024;
		return df.format(length + remainder) + unit;

	}

	/**
	 * 获取片文件保存位置
	 * 
	 * @param chunkInfo
	 * @param rootPath
	 * @return File
	 * @Author Administrator
	 * @Date 2017年9月21日
	 */
	public static File getReadySpace(FileChunkInfo chunkInfo, String rootPath) {
		String fileName = chunkInfo.getFileName();
		File fold =  getChunkFlod(chunkInfo,rootPath);
		if(fold==null){
			return null;
		}
		if (!fold.exists()) {
			// 创建片文件保存在临时文件夹
			fold.mkdir();
		}
		String chunkName = chunkInfo.getChunkIndex() + fileName.substring(fileName.lastIndexOf('.'));
		File chunkFile = new File(fold, chunkName);
		if (chunkFile.exists()) {
			try {
				chunkFile.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return chunkFile;

	}

	/**
	 * 合并文件
	 * 
	 * @param chunkInfo
	 * @param rootPath
	 * @return File
	 * @Author Administrator
	 * @Date 2017年9月21日
	 */
	public static File mergerFile(FileChunkInfo chunkInfo, String rootPath) {
		File dir = getChunkFlod(chunkInfo,rootPath);
		File destFile = null;
		//对文件合并代码块加锁，防止并发合并文件，发生文件合并错误。
		synchronized(dir){
			if (dir.isDirectory()) {
				List<File> fileList = getFileChunks(dir);
				if(fileList==null){
					return null;
				}
				destFile = new File(dir, chunkInfo.getFileName());
				for (File f : fileList) {
					try {
						saveFile(destFile, f, true);
						if (!f.delete()) {
							throw new IOException("分片删除失败");
						}
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		}
		return destFile;
	}

	/**
	 * 或的片文件所在的临时文件夹
	 * @param chunkInfo
	 * @param rootPath
	 * @return File
	 * @Author Administrator
	 * @Date 2017年9月21日
	 */
	public static File getChunkFlod(FileChunkInfo chunkInfo, String rootPath) {
		String fileName = chunkInfo.getFileName();
		String flodName = fileName.substring(0, fileName.lastIndexOf(".")) + chunkInfo.getUuid();
		File dir = new File(rootPath, flodName);
		if(!dir.exists()){
			dir.mkdir();
	 	}
		return dir;
	}

	/**
	 * 获取指定文件夹中的所有文件，排除临时文件，并按顺序排列
	 * 
	 * @param dir
	 * @return List<File>
	 * @Author Administrator
	 * @Date 2017年9月21日
	 */
	public static List<File> getFileChunks(File dir) {
		if(dir==null){
			throw new ServiceException("文件不存在");
		}

		File[] files = dir.listFiles(new FileFilter() {
			
			@Override
			public boolean accept(File pathname) {
				if(pathname.getName().endsWith(".tmp")){
					return false;
				}
				return true;
			}
		});
		List<File> fileList =null;
		if(files==null||files.length==0){
			return null;
		}
		//文件块数不为0
		fileList = new ArrayList<File>(Arrays.asList(files));
		Collections.sort(fileList, new Comparator<File>() {
			
			@Override
			public int compare(File o1, File o2) {
				String name1=o1.getName();
				String name2=o2.getName();
				String order1=name1.substring(0,name1.lastIndexOf('.'));
				String order2=name2.substring(0,name2.lastIndexOf('.'));
				if (Integer.valueOf(order1) < Integer.valueOf(order2)) {
					return -1;
				}
				return 1;
			}
		});
		return fileList;
	}

}
